package com.base.themvx.v

import android.annotation.SuppressLint
import android.app.Activity
import android.app.Application
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.content.res.Resources
import android.graphics.Color
import android.os.Bundle
import android.util.ArrayMap
import android.util.SparseArray
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.Toast
import androidx.annotation.*
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelStoreOwner
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.base.themvx.AppLog
import com.base.themvx.LanguageManager
import com.base.themvx.R
import com.base.themvx.action.LogAction
import com.base.themvx.assignNavigationBarColor
import com.base.themvx.defNonSyncLazy
import com.base.themvx.immersiveWindow
import com.base.themvx.pop.CommonLoadingCenterPop
import com.base.themvx.utils.ImageUtil
import com.base.themvx.utils.ScreenUtils
import com.base.themvx.vm.ViewModelsProviderFactory
import com.blankj.utilcode.util.ToastUtils


/**
 * @author fee
 * <P> DESC:
 * 通用的基础 的[V]视图层
 * </P>
 */
abstract class BaseViewDelegate(protected val mContext: Context) : IView, View.OnClickListener, LogAction {

    companion object Infos {

        val sStatusBarHeight: Int  by defNonSyncLazy {
            ScreenUtils.getStatusBarHeight()
        }
    }

    protected val TAG by defNonSyncLazy {
        javaClass.simpleName
    }

    protected var mIsLogDebug = false

    private val mToastUtil: ToastUtils by defNonSyncLazy {
        val maker = ToastUtils.getDefaultMaker()
//        maker.setBgResource(R.drawable.msg_notify_toast_bg)
//            .setTextColor(Color.WHITE)
//            .setTextSize(15)
        maker
    }

    /**
     * 本　视图层的　内容视图的根控件，可用来给子类使用　ViewBinding
     */
    protected var rootView: View? = null

    /**
     * 本视图层当前是否 不可见
     * def = false
     */
    protected var mIsHidden = false


    /**
     * 当前View层可能需要查找出的各视图控件
     * 1、之所以使用 稀释数组缓存起来，是为了减少在调用[findViewById]方法获取View时减少遍历View树
     * 2、方便子类可以不声明各控件变量情况下，直接可多次使用[findView]来拿到想要的控件
     */
    protected var viewsCache: SparseArray<View>? = null

    /**
     * 本视图层停留时长
     */
    protected var mPageStayTs: Long = 0

    /**
     * 本视图层开始时长
     */
    protected var mPageStartTs: Long = 0

    protected var mIsNeedTrackStayTime = false

    /**
     * 如果本视图层 嵌入在 Fragment 中,则所有者为 当前Fragment,如果嵌入在 Activity中,则所有者为 当前 Activity
     */
    protected var mViewModelStoreOwner: ViewModelStoreOwner? = null

    /**
     * 当前的　V　视图所归属的　生命周期所有者对象
     * 为当前所处容器：Activity　或者　　Fragment
     */
    protected var mLifecycleOwner: LifecycleOwner? = null

    var isNeedCancelToastAtFinish = false

    /**
     * added by fee 2021-03-13: 由于本视图层是使用 [LayoutInflater] [inflate]出界面布局的方式，
     * 而如果 [container]外部没有指定容器View的Case 下，XML中根 View 所写的 布局参数并不会被保留
     * 造成开发者在 XML 中写的 边距等属性无效，所以这里统一处理，并可以让子类 自主配置
     * def = false 因为大多数情况下，我们在 XML中的根 View不会写 边距等属性
     */
    protected var isNeedKeepXmlRootViewParams = false

    /**
     * 注：子类甚至是可以 不通过 [provideVLayoutRes]方式提供视图层的 布局资源的，
     * 而是可以让 [provideVLayoutRes]=0而直接 重写本方法或者 重写[provideTheDelegateView]以提供本视图代理层最终对外提供的View
     * @param container 将要装载 本 视图层的容器 View; eg.: 当本视图层是提供给 [Fragment]时
     * @param savedInstanceState [Activity] 重绘时临时存储了状态数据的 对象
     * @return 本视图层最终创建的 视图 View
     */
    override fun onCreateView(container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val provideVLayoutRes = provideVLayoutRes()
        if (provideVLayoutRes != 0) {
            var theTempContainerView = container
            if (theTempContainerView == null && isNeedKeepXmlRootViewParams) {
                theTempContainerView = FrameLayout(mContext)
            }
            rootView = LayoutInflater.from(mContext)
                .inflate(provideVLayoutRes, theTempContainerView, false)
        } else {
            rootView = provideTheDelegateView()
        }
        return peekRootView()
    }

    /**
     * 子类可以 在不指定 [provideVLayoutRes]视图布局资源的情况下
     * 重写该方法以提供本视图层
     * def return null
     */
    protected open fun provideTheDelegateView(): View? {

        return null
    }

    protected var mDataIntent: Intent? = null
    protected var mDataBundle: Bundle? = null

    /**
     * 在该方法回调里初始化 Views
     * @param isInitState 是否为初始化状态,eg.: [Activity]的[onCreate]生命周期方法回调时；
     * @param dataIntent 从其他地方 跳转/路由 过来时所携带的 [Intent]
     * @param extraData 从其他地方 跳转/路由 过来时所携带的 [Bundle]数据； eg.: [Fragment]的初始化
     */
    override fun initViews(isInitState: Boolean, dataIntent: Intent?, extraData: Bundle?) {
        mDataIntent = dataIntent
        mDataBundle = extraData
        if (isInitState) {
            initViews(true)
            initDatasAndListeners()
        }
    }

    /**
     * 初始化各视图
     */
    protected open fun initViews(isInitState: Boolean) {

    }

    /**
     * 初始化数据以及各种监听者、数据观察者等
     */
    protected open fun initDatasAndListeners() {

    }

    /**
     * 本 接口View 的根View，可以提供给 [Activity] 或者 [Fragment]
     */
    final override fun peekRootView(): View? = rootView

    var isEnableCachViews = true

    /**
     * 根据 指定的 View的 ID来查找对应的View
     * @param targetViewId View所声明的ID
     * @return null or View
     */
    override fun <V : View> findView(@IdRes targetViewId: Int): V {
        var findedView = viewsCache?.get(targetViewId)//首先在 缓存中找,目的是 减少 View 树的遍历
        if (findedView == null) {
            findedView = super.findView(targetViewId)
            if (isEnableCachViews && findedView != null) {
                if (viewsCache == null) {
                    viewsCache = SparseArray()
                }
                viewsCache?.put(targetViewId, findedView)
            }
        }
        return findedView as V//如果 findedView == null 会抛出异常
    }

    protected fun <V : View> view(@IdRes targetViewId: Int): V = findView(targetViewId)

    protected fun <V : View> viewOfHost(@IdRes targetViewId: Int): V {
        var findedView = viewsCache?.get(targetViewId)
        if (findedView == null) {
            val activity: Activity = mContext as Activity
            findedView = activity.findViewById(targetViewId)
            if (isEnableCachViews && findedView != null) {
                if (viewsCache == null) {
                    viewsCache = SparseArray()
                }
                viewsCache?.put(targetViewId, findedView)
            }
        }
        return findedView as V
    }

    protected fun <V : View> safeFindView(@IdRes targetViewId: Int): V? {
        return try {
            view(targetViewId)
        } catch (ignore: Exception) {
            null
        }
    }

    /**
     * 将dimen资源id,转换为系统中的px值
     * @param dimenResId 定义的dimen 资源 ID
     * @return px像素值
     */
    fun dimenResPxValue(@DimenRes dimenResId: Int): Int {
        return mContext.resources.getDimensionPixelSize(dimenResId)
    }

    fun getString(@StringRes strResId: Int): String {
        return mContext.getString(strResId)
    }

    //------ 关于 通用 Toast @start ---------


    /**
     * 显示一个 居中 Toast，
     * 方法名以 toast前缀 便捷限定即为 Toast功能
     * 注：如果子类有不同的 Toast方案，重写之
     */
    open fun toastCenter(toastMsg: CharSequence?, duration: Int = Toast.LENGTH_SHORT) {
        if (toastMsg.isNullOrBlank()) {
            return
        }
        //to do: 后续更换为其他 toast
//        Toast.makeText(mContext, toastMsg, duration).show()
//        ToastUtils.getDefaultMaker().setGravity(Gravity.CENTER,0,0)
//            .show(toastMsg)
        val isLongShow = duration == Toast.LENGTH_LONG
        mToastUtil.setGravity(Gravity.CENTER, 0, 0)
            .setDurationIsLong(isLongShow)
            .show(toastMsg)
    }

    fun toastCenter(@StringRes toastMsgResId: Int) {
        toastCenter(getString(toastMsgResId))
    }

    open fun toastTop(toastMsg: CharSequence?, duration: Int = Toast.LENGTH_SHORT) {
        if (toastMsg.isNullOrBlank()) {
            return
        }
        val isLongShow = duration == Toast.LENGTH_LONG
        mToastUtil.setGravity(Gravity.TOP, 0, 0)
            .setDurationIsLong(isLongShow)
            .show(toastMsg)
    }

    fun toastTop(@StringRes toastMsgResId: Int) {
        toastTop(getString(toastMsgResId))
    }

    open fun toastBottom(toastMsg: CharSequence?, duration: Int = Toast.LENGTH_SHORT) {
        if (!toastMsg.isNullOrBlank()) {
            val isLongShow = duration == Toast.LENGTH_LONG
            mToastUtil.setGravity(Gravity.BOTTOM, 0, 0)
                .setDurationIsLong(isLongShow)
                .show(toastMsg)
        }
    }

    fun toastBottom(@StringRes toastMsgResId: Int) {
        toastBottom(getString(toastMsgResId))
    }
    //------ 关于 通用 Toast @end -----------


    //------ 关于 通用 路由跳转 @start ---------

    open fun jumpToActivity(
        startIntent: Intent,
        startReqCode: Int,
        needFeedbackResult: Boolean = false
    ) {
        if (!needFeedbackResult) {
            mContext.startActivity(startIntent)
        } else {
            if (mContext is Activity) {
                mContext.startActivityForResult(startIntent, startReqCode)
            }
        }
    }

    fun jumpToActivity(
        targetActivityClass: Class<*>,
        reqCode: Int = 0,
        needFeedbackResult: Boolean = false
    ) {
        jumpToActivity(Intent(mContext, targetActivityClass), reqCode, needFeedbackResult)
    }

    fun jumpToActivity(
        targetActivityClass: Class<*>,
        reqCode: Int = 0,
        needFeedbackResult: Boolean = false,
        extraData: Intent.() -> Unit
    ) {
        val startIntent = Intent(mContext, targetActivityClass)
        startIntent.extraData()
        jumpToActivity(startIntent, reqCode, needFeedbackResult)
    }
    //------ 关于 通用 路由跳转 @end -----------


    //------- 关于 调试日志输出 @start ----------
    open fun i(logTag: String? = TAG, logMsg: String) {
        AppLog.i(logTag ?: TAG, logMsg)
    }

    open fun e(logTag: String? = TAG, logMsg: String) {
        AppLog.e(logTag ?: TAG, logMsg)
    }

    open fun d(logTag: String? = TAG, logMsg: String) {
        AppLog.d(logTag ?: TAG, logMsg)
    }

    //------- 关于 调试日志输出 @end   ----------


    protected open fun dialogHint(
        @StringRes hintTitleRes: Int,
        @StringRes hintMessageRes: Int,
        @StringRes cancelBtnTextRes: Int,
        @StringRes sureBtnTextRes: Int,
        hintDialogInCase: Int
    ) {
        dialogHint(
            if (hintTitleRes == 0) {
                ""
            } else {
                getString(hintTitleRes)
            },
            getString(hintMessageRes),
            cancelBtnText = getString(cancelBtnTextRes),
            sureBtnText = getString(sureBtnTextRes),
            dialogInCase = hintDialogInCase
        )
    }

    protected open fun dialogHint(
        hintTitle: CharSequence?,
        hintMsg: CharSequence?,
        hitMsgTextGravity: Int = Gravity.CENTER_HORIZONTAL,
        cancelBtnText: CharSequence?,
        sureBtnText: CharSequence?,
        dialogInCase: Int
    ) {

    }

    protected open fun dialogHint(
        hintTitle: CharSequence?,
        hintMsg: CharSequence?,
        cancelBtnText: CharSequence?,
        sureBtnText: CharSequence?,
        dialogInCase: Int
    ) {

    }

    protected open fun dismissHintDialog() {

    }
    //------- 关于 通用提示性 Dialog @end   ----------

    //------- 关于 通用loading @start ----------

    //------- 关于 通用loading @end   ----------


    /**
     * 关联 宿主的 ViewModelStoreOwner
     */
    override fun attachViewModelStoreOwner(theViewModelStoreOwner: ViewModelStoreOwner?) {
        mViewModelStoreOwner = theViewModelStoreOwner
    }

    /**
     * 关联 宿主的 LifecycleOwner
     */
    override fun attachLifecycleOwner(theLifecycleOwner: LifecycleOwner?) {
        mLifecycleOwner = theLifecycleOwner
    }

    protected open fun <App : Application> peekAppInstance(): App {
        return mContext.applicationContext as App
    }

    fun <V : View> bindViewOnClickListener(
        @IdRes theViewID: Int,
        onClickListener: View.OnClickListener = this
    ): V {
        val theV: V = findView(theViewID)
        if (theV != null) {
            bindViewOnClickListener(theV, onClickListener)
        }
        return theV
    }

    fun bindViewOnClickListener(theView: View?, onClickListener: View.OnClickListener = this) {
        theView?.setOnClickListener(onClickListener)
    }

    fun bindOnClickListener(vararg views: View?, listener: View.OnClickListener = this) {
        views.forEach {
            it?.setOnClickListener(listener)
        }
    }

    override fun onClick(v: View?) {

    }

    open fun commonLoadImgData(
        @IdRes imgViewId: Int,
        imgUrl: String?,
        @DrawableRes defHoldImgRes: Int,
        useAppContext: Boolean
    ) {
        val ivImg: ImageView = findView(imgViewId)
        var useContext: Context? = ivImg.context
        if (useAppContext) {
            useContext = ivImg.context.applicationContext
        }
        ImageUtil.loadImage(useContext, imgUrl, defHoldImgRes, defHoldImgRes, ivImg)
    }

    //------------ 通用加载图片 方法 @Start
    /**
     * 使用 Application 级的Context 加载图片
     * @param imgViewId
     * @param imgUrl
     * @param defHoldImgRes
     */
    open fun commonLoadImgData(
        @IdRes imgViewId: Int,
        imgUrl: String?,
        @DrawableRes defHoldImgRes: Int
    ) {
        val ivImg: ImageView = findView(imgViewId)
        commonLoadImgData(ivImg, imgUrl, defHoldImgRes)
    }

    open fun commonLoadImgData(
        imgView: ImageView?,
        imgUrl: String?,
        @DrawableRes defHoldImgRes: Int = R.drawable.shape_4_def_img,
        isDontAnimated: Boolean = true
    ) {
        if (imgView == null || imgUrl.isNullOrBlank()) {
            return
        }
        ImageUtil.loadImage(
            imgView.context,
            imgUrl,
            defHoldImgRes,
            defHoldImgRes,
            imgView,
            null,
            isDontAnimated
        )
    }

    open fun isEmpty(charSequence: CharSequence?): Boolean {
        return charSequence.isNullOrBlank()
    }

    fun peekContextAsActivity(): Activity? {
        return if (mContext is Activity) {
            mContext
        } else {
            null
        }
    }

    /**
     * 注：如果当前的 View是 [Fragment]的，则如果不是想把 宿主 [Activity]结束的话，则调用该方法不合适
     */
    open fun reqHostFinish() {
        peekContextAsActivity()?.finish()
    }

    protected fun reqHostRecreate(){
        peekContextAsActivity()?.recreate()
    }

    /**
     * 会调用　宿主　Activity　的finish()
     */
    fun finish() = reqHostFinish()

    /**
     * 会调用　宿主　Activity　的　onBackPressed()　等同于点击返回键
     */
    fun backExit() = peekContextAsActivity()?.onBackPressed()

    fun peekContextAsAppCompatActivity(): AppCompatActivity? {
        return if (mContext is AppCompatActivity) {
            mContext
        } else {
            null
        }
    }

    /**
     * 观察 [LiveData]
     * 便捷的让 [LiveData] 注册观察者
     */
    protected fun <D> observeLiveData(
        obserbleLiveData: LiveData<D>?,
        onDataChangedBlock: (D) -> Unit
    ): Observer<D>? {
        var aObserver: Observer<D>? = null
        obserbleLiveData?.let {
            aObserver = Observer(onDataChangedBlock)
            it.observe(mLifecycleOwner!!, aObserver!!)
        }
        return aObserver
    }

    /**
     * 观察 [LiveData]
     * @param obserbleLiveData [LiveData]对象,被观察的数据
     * @param theObserver 观察者接口实现
     */
    protected fun <D> observeLiveData(obserbleLiveData: LiveData<D>?, theObserver: Observer<D>) {
        obserbleLiveData?.observe(mLifecycleOwner!!, theObserver)
    }

    protected fun <D> observeLiveDataForever(
        obserbleLiveData: LiveData<D>?,
        theObserver: Observer<D>
    ) {
        obserbleLiveData?.observeForever(theObserver)
    }

    protected fun <D> observeLiveDataForever(
        obserbleLiveData: LiveData<D>?,
        onDataChangedBlock: (D) -> Unit
    ): Observer<D>? {
        var aObserver: Observer<D>? = null
        obserbleLiveData?.let {
            aObserver = Observer(onDataChangedBlock)
            it.observeForever(aObserver!!)
        }
        return aObserver
    }

    protected fun <D> unObserveLiveData(obserbleLiveData: LiveData<D>?, theObserver: Observer<D>) {
        obserbleLiveData?.removeObserver(theObserver)
    }

    /**
     * 获取 对应的 [ViewModel]
     */
    protected fun <VM : ViewModel> getViewModelOfOwner(viewModelClass: Class<out VM>): VM {
        return getViewModel(viewModelClass)
    }

    /**
     * 可以指定　@param [ViewModelStoreOwner]　的获取　[ViewModel]
     */
    protected fun <VM : ViewModel> getViewModel(
        viewModelClass: Class<out VM>,
        viewModelStoreOwner: ViewModelStoreOwner? = mViewModelStoreOwner!!
    ): VM {
        return ViewModelsProviderFactory.getViewModel(
            viewModelStoreOwner!!,
            viewModelClass
        )
    }

    open fun visibleMe(isVisible: Boolean, isNeedGoneWhenNotVisible: Boolean = false) {
        rootView?.visibility = if (isVisible) {
            View.VISIBLE
        } else {
            if (isNeedGoneWhenNotVisible) {
                View.GONE
            } else {
                View.INVISIBLE
            }
        }
        mIsHidden = !isVisible
        onHiddenChanged(!isVisible)
    }

    /**
     * 本视图层自身的可见性回调
     */
    open fun onHiddenChanged(isHidden: Boolean) {

    }

    /**
     * 本 View 层的 调试信息
     * @return def = ""
     */
    override fun theDebugInfo(): String {
        return TAG
    }

    private var mIsHasOtherViewDelegates = false

    /**
     * 与本[BaseViewDelegate] 一起协同的 [BaseViewDelegate]数据集
     */
    protected val mSynergicViewDelegates by defNonSyncLazy {
        mIsHasOtherViewDelegates = true
        mutableListOf<BaseViewDelegate>()
    }

    /**
     * 本 [BaseViewDelegate] 协同其他的 [BaseViewDelegate]
     * 注意：[BaseViewDelegate] 与 [BaseViewDelegate] 嵌套时，要注意 this的指代关系
     */
    fun synergicViewDelegate(viewDelegate: BaseViewDelegate) {
        if (viewDelegate == this) {
            return
        }
        viewDelegate.attachLifecycleOwner(mLifecycleOwner)
        viewDelegate.attachViewModelStoreOwner(mViewModelStoreOwner)
        mSynergicViewDelegates.add(viewDelegate)
    }

    //------------- 宿主生命周期的 @start --------------------------
    override fun onResume() {
        super.onResume()
        if (mIsHasOtherViewDelegates) {
            mSynergicViewDelegates.forEach {
                it.onResume()
            }
        }
        if (mIsNeedTrackStayTime && mPageStartTs < 1) {
            mPageStartTs = System.currentTimeMillis()
        }
    }

    override fun onStart() {
        super.onStart()
        if (mIsHasOtherViewDelegates) {
            mSynergicViewDelegates.forEach {
                it.onStart()
            }
        }
    }

    override fun onStop() {
        super.onStop()
        if (mIsHasOtherViewDelegates) {
            mSynergicViewDelegates.forEach {
                it.onStop()
            }
        }
        stackStayTime()
    }

    @CallSuper
    override fun onHostFinish() {
        if (mIsHasOtherViewDelegates) {
            mSynergicViewDelegates.forEach {
                it.onHostFinish()
            }
        }
        stackStayTime()
    }

    private fun stackStayTime() {
        if (mIsNeedTrackStayTime && mPageStartTs > 1) {
            //页面关闭时，累积一次停留时长
            mPageStayTs += System.currentTimeMillis() - mPageStartTs
            mPageStartTs = 0
        }
    }

    override fun onDetach() {
        super.onDetach()
        if (mIsHasOtherViewDelegates) {
            mSynergicViewDelegates.forEach {
                it.onDetach()
            }
        }
    }

    override fun onConfigurationChanged(newConfig: Configuration?) {
        super.onConfigurationChanged(newConfig)
        if (mIsHasOtherViewDelegates) {
            mSynergicViewDelegates.forEach {
                it.onConfigurationChanged(newConfig)
            }
        }
    }

    override fun onPause() {
        super.onPause()
        if (mIsHasOtherViewDelegates) {
            mSynergicViewDelegates.forEach {
                it.onPause()
            }
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (mIsHasOtherViewDelegates) {
            mSynergicViewDelegates.forEach {
                it.onActivityResult(requestCode, resultCode, data)
            }
        }
    }

    override fun onSaveInstanceState(outState: Bundle?) {
        super.onSaveInstanceState(outState)
        if (mIsHasOtherViewDelegates) {
            mSynergicViewDelegates.forEach {
                it.onSaveInstanceState(outState)
            }
        }
    }
    //------------- 宿主生命周期的 @end --------------------------

    //------------- loading @start -----------------------------

    protected var mLoadingPop: CommonLoadingCenterPop? = null

    /**
     * 如果不是全屏样式的 页面，则可以指定底部导航栏的背景颜色
     */
    protected var mNavigationBarColor = 0xFF0D0E12.toInt()

    protected fun showLoading(loadingHint: CharSequence, isCancelable: Boolean = false) {
        if (mLoadingPop == null) {
            val popView = CommonLoadingCenterPop.show(
                mContext,
                loadingHint,
                mNavigationBarColor,
                isPageHasNavigationBar(),
                isCancelable
            )
//            val popView = XPopup.Builder(mContext)
//                .dismissOnBackPressed(isCancelable)
//                .dismissOnTouchOutside(false)
//                .navigationBarColor(mNavigationBarColor)
//                .hasNavigationBar(isPageHasNavigationBar())
//                .asLoading(loadingHint)
//                .show()
            mLoadingPop = popView
        } else {
            mLoadingPop?.popupInfo?.let {
                it.isDismissOnBackPressed = isCancelable
            }
            mLoadingPop?.showWithTitle(loadingHint)
//            mLoadingPop?.show()
        }
    }

    protected fun showLoading(
        @StringRes hintTextResId: Int = R.string.loading,
        isCancelable: Boolean = false
    ) {
        showLoading(getString(hintTextResId), isCancelable)
    }

    protected open fun dismissLoading() {
        mLoadingPop?.dismiss()
    }
    //------------- loading @end -----------------------------


    protected fun activityResult(resultCode: Int, data: Intent? = null) {
        peekContextAsActivity()?.setResult(resultCode, data)
    }

    /**
     * 本视图层是否可见
     */
    fun isMyselfVisible() = rootView?.isVisible ?: false

    /**
     * 如果有些界面需要 沉浸式绘制到系统状态栏区域，则可以手动的 把状态栏的高度当做内容视图的内上边距
     * 达到适配目的
     */
    protected fun paddingStatusBarHeight() {
        val statusBarHeight = sStatusBarHeight
        if (statusBarHeight > 0) {
            rootView?.updatePadding(top = statusBarHeight)
        }
    }

    protected fun paddingStatusBarHeight(theView: View?) {
        val statusBarHeight = sStatusBarHeight
        if (statusBarHeight > 0) {
            theView?.updatePadding(top = statusBarHeight)
        }
    }

    protected fun paddingNavigateBarHeight() {
        val navigationBar = ScreenUtils.getNavigationBarHeight()
        if (navigationBar > 0) {
            rootView?.updatePadding(bottom = navigationBar)
        }
    }

    /**
     * 请求权限
     */
    @SuppressLint("NewApi")
    protected fun reqPermissions(reqCode: Int, vararg permissions: String) {
        peekContextAsActivity()?.requestPermissions(permissions, reqCode)
    }

    /**
     * 判断是否当前　App　已被授予了　相应的权限　
     * @param permission 指定的权限
     * @return true: 授予了权限;　false: 无该权限
     */
    protected fun isHasPermission(permission: String): Boolean {
        if (permission.isBlank()) {
            return false
        }
        return ContextCompat.checkSelfPermission(
            mContext,
            permission
        ) == PackageManager.PERMISSION_GRANTED
    }

    /**
     * 关于权限申请的结果回调
     * @param requestCode 本次申请请求码
     * @param permissions 本次总共要申请的权限数组
     * @param grantResults 本次用户同意了的权限申请一一对应状态码数组
     */
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ): Boolean {
        val stateMap = ArrayMap<String, Boolean>()
        permissions.forEachIndexed { index, p ->
            val state = grantResults[index]
            val isGranted = state == PackageManager.PERMISSION_GRANTED
            stateMap[p] = isGranted
        }
        onPermissionResult(requestCode, stateMap)
        return true
    }

    /**
     * 权限申请的结果回调
     * @param reqCode 本次申请请求码
     * @param permissionStates 本批次权限一一对应的申请结果状态
     */
    protected open fun onPermissionResult(reqCode: Int, permissionStates: Map<String, Boolean>) {

    }

    /**
     * 本视图层是否底部有导航栏显示
     * def = true
     */
    protected open fun isPageHasNavigationBar() = true

    protected fun assignNavigationBarColor(@ColorInt color: Int) {
        mNavigationBarColor = color
        peekContextAsActivity()?.assignNavigationBarColor(color)
    }

    /**
     * 每次都构建新的对象，这样的目的是 让 LayoutInflater 是当前的 资源配置环境下的
     */
    protected fun fetchLayoutInflater(): LayoutInflater {
        return LayoutInflater.from(mContext)
    }

    /**
     * 本视图所附属的 宿主是否 不可见
     * def = false
     */
    protected var mIsHostHidden = false

    /**
     * 主要是 位于 Fragment 容器中时，可能的回调
     */
    override fun onHostHiddenChanged(isHidden: Boolean) {
        mIsHostHidden = isHidden
    }

    override fun getResource(): Resources? {
        //需要使用当前系统切换的语言资源
        return LanguageManager.getMe().getAppRes()
    }

    /**
     * 注册App本地(域内)的广播接收者
     */
    fun registerLocalBroadcastReceiver(
        receiver: BroadcastReceiver?,
        intentConfig: IntentFilter.() -> Unit
    ) {
        if (receiver == null) {
            return
        }
        val intentFilter = IntentFilter()
        intentFilter.intentConfig()
        LocalBroadcastManager.getInstance(mContext)
            .registerReceiver(receiver, intentFilter)
    }

    fun unRegisterLocalReceiver(receiver: BroadcastReceiver?) {
        if (receiver != null) {
            LocalBroadcastManager.getInstance(mContext)
                .unregisterReceiver(receiver)
        }
    }

    protected fun checkedInputTextOrToastHint(text: String, hintTextRes: Int): Boolean {
        if (text.isBlank()) {
            if (hintTextRes != 0) {
                toastCenter(hintTextRes)
            }
            return false
        }
        return true
    }

    protected fun configImmersiveWindow() {
        peekContextAsActivity()?.immersiveWindow(
            drawStatusBarBg = true,
            isLightStatusBar = false,
            translucentNavBar = false,
            hideNavigation = false,
            navBarColor = 0
        )
    }
}